package baseFx.database.where.impl;

import baseFx.database.DbEntity;
import baseFx.database.SqlCore;
import baseFx.database.SqlParam;
import baseFx.database.where.ExecuteWhere;
import baseFx.database.where.WhereParser;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class MysqlWhere extends BaseWhereParser implements WhereParser {
    public MysqlWhere(SqlCore core) {
        super(core);
    }

    @Override
    public SqlParam parse(ExecuteWhere where) {
        Class table = where.getTable();
        DbEntity entity = DbEntity.get(table);
        SqlParam param = new SqlParam();
        String split = where.splitCondition().trim();
        List<String> wlist = new ArrayList<>();

        List items = where.in();
        if (items != null) {
            List<String> args = parseIn(true, param, table, items, entity);
            if (args.size() > 0) {
                wlist.addAll(args);
            } else {
                wlist.add("1=2");
            }
        }
        items = where.inOrNull();
        if (items != null) {
            List<String> args = parseIn(true, param, table, items, entity);
            if (args.size() > 0) {
                wlist.addAll(args);
            }
        }
        items = where.notIn();
        if (items != null) {
            List<String> args = parseIn(false, param, table, items, entity);
            if (args.size() > 0) {
                wlist.addAll(args);
            } else {
                wlist.add("1=2");
            }
        }
        items = where.notInOrNull();
        if (items != null) {
            List<String> args = parseIn(false, param, table, items, entity);
            if (args.size() > 0) {
                wlist.addAll(args);
            }
        }
        Object model = where.eq();
        if (model != null) {
            Map<String, Object> values = entity.getValues(model);
            for (String name : values.keySet()) {
                String pn = "eq_" + name;
                wlist.add(escape(name) + "=" + paramName(pn));
                param.args.put(pn, values.get(name));
            }
        }
        model = where.neq();
        if (model != null) {
            Map<String, Object> values = entity.getValues(model);
            for (String name : values.keySet()) {
                String pn = "nq_" + name;
                wlist.add(escape(name) + "!=" + paramName(pn));
                param.args.put(pn, values.get(name));
            }
        }
        model = where.greater();
        if (model != null) {
            Map<String, Object> values = entity.getValues(model);
            for (String name : values.keySet()) {
                Object value = values.get(name);
                String pn = "gr_" + name;
                wlist.add(escape(name) + ">" + paramName(pn));
                param.args.put(pn, value);
            }
        }
        model = where.less();
        if (model != null) {
            Map<String, Object> values = entity.getValues(model);
            for (String name : values.keySet()) {
                Object value = values.get(name);
                String pn = "le_" + name;
                wlist.add(escape(name) + "<" + paramName(pn));
                param.args.put(pn, value);
            }
        }
        model = where.greaterEq();
        if (model != null) {
            Map<String, Object> values = entity.getValues(model);
            for (String name : values.keySet()) {
                Object value = values.get(name);
                String pn = "greq_" + name;
                wlist.add(escape(name) + ">=" + paramName(pn));
                param.args.put(pn, value);
            }
        }
        model = where.lessEq();
        if (model != null) {
            Map<String, Object> values = entity.getValues(model);
            for (String name : values.keySet()) {
                Object value = values.get(name);
                String pn = "leeq_" + name;
                wlist.add(escape(name) + "<=" + paramName(pn));
                param.args.put(pn, value);
            }
        }
        model = where.like();
        if (model != null) {
            Map<String, Object> values = entity.getValues(model);
            for (String name : values.keySet()) {
                Object value = values.get(name);
                if (String.class.isInstance(value)) {
                    String text = value.toString();
                    String pn = "lk_" + name;
                    if (text.startsWith("%")) {
                        text = text.substring(1);
                        wlist.add(escape(name) + " like concat('%'," + paramName(pn) + ")");
                    } else if (text.endsWith("%")) {
                        text = text.substring(0, text.length() - 1);
                        wlist.add(escape(name) + " like concat(" + paramName(pn) + ",'%')");
                    } else {
                        wlist.add(escape(name) + " like concat('%'," + paramName(pn) + ",'%')");
                    }
                    param.args.put(pn, text);
                }
            }
        }
        model = where.notLike();
        if (model != null) {
            Map<String, Object> values = entity.getValues(model);
            for (String name : values.keySet()) {
                Object value = values.get(name);
                if (String.class.isInstance(value)) {
                    String text = value.toString();
                    String pn = "nlk_" + name;
                    if (text.startsWith("%")) {
                        text = text.substring(1);
                        wlist.add(escape(name) + " not like concat('%'," + paramName(pn) + ")");
                    } else if (text.endsWith("%")) {
                        text = text.substring(0, text.length() - 1);
                        wlist.add(escape(name) + " not like concat(" + paramName(pn) + ",'%')");
                    } else {
                        wlist.add(escape(name) + " not like concat('%'," + paramName(pn) + ",'%')");
                    }
                    param.args.put(pn, text);
                }
            }
        }
        model = where.isNotNull();
        if (model != null) {
            Map<String, Object> values = entity.getValues(model);
            for (String name : values.keySet()) {
                wlist.add(escape(name) + " is not null");
            }
        }
        model = where.isNull();
        if (model != null) {
            Map<String, Object> values = entity.getValues(model);
            for (String name : values.keySet()) {
                wlist.add(escape(name) + " is null");
            }
        }
        StringBuilder sql = new StringBuilder();
        if (wlist.size() > 0) {
            sql.append(" where ").append(String.join(" " + split + " ", wlist));
        } else if (where.allowEmptyCondition() == false) {
            throw new RuntimeException("至少需要一个where条件");
        }
        param.command = sql.toString();
        return param;
    }
}
